package com.moli.iov.admin.component;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.moli.iov.cache.RedisUtil;
import com.moli.iov.exception.BusinessException;
import com.moli.iov.sys.constants.Constant;
import com.moli.iov.sys.model.dto.res.LoginDto;
import com.moli.iov.sys.model.po.Permission;
import com.moli.iov.sys.model.po.User;
import com.moli.iov.util.JwtTokenUtil;
import com.moli.iov.util.StringUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 权限缓存
 * </p>
 *
 * @author zql
 * @since 2019/9/26 14:53
 */
@Slf4j
@Component
public class CacheManger {

  @Autowired
  private RedisUtil redisUtil;

  @Value("${jwt.expiration}")
  private Long expiration;

  @Value("${pwd.salt}")
  private String salt;

  @Value("${jwt.tokenHead}")
  private String tokenHead;

  /**
   * 登录成功添加缓存
   */
  public void setLoginCache(LoginDto loginDto) {
    String account = loginDto.getUser().getAccount();
    this.setPermission(account, convertMap(loginDto.getApiPermissions()));
    this.setUser(loginDto.getUser());
    this.setToken(account, loginDto.getToken().substring(this.tokenHead.length()));
  }

  /**
   * 权限List转Map
   */
  private Map<String, Permission> convertMap(List<Permission> apiPermissions) {
    Map<String, Permission> map = new HashMap<>();
    apiPermissions.forEach(api -> {
      if(StringUtil.isNotBlank(api.getApiUrl())){
        map.put(api.getApiUrl(), api);
      }
    });
    return map;
  }

  /**
   * 清除登录缓存
   */
  public void removeLoginCache(String account) {
    removePermission(account);
  }

  /**
   * 缓存权限
   */
  public void setPermission(String account, Map<String, Permission> permissions) {
    redisUtil.set(Constant.DEFAULT_PERMISSION + account, JSONObject.toJSONString(permissions),
        expiration);
  }

  /**
   * 清空权限缓存
   */
  public void removePermission(String account) {
    redisUtil.delete(Constant.DEFAULT_PERMISSION + account);
  }

  /**
   * 获取当前登录用户的权限
   */
  public Map<String, Permission> getPermission(String account) {

    String pers = redisUtil.get(Constant.DEFAULT_PERMISSION + account);

    if (StringUtil.isBlank(pers)) {
      throw new BusinessException("无权限");
    }

    Map<String, Permission> map = JSONObject
        .parseObject(pers, new TypeReference<Map<String, Permission>>() {
        });

    if (map == null) {
      throw new BusinessException("无权限");
    }

    return map;
  }

  /**
   * 缓存登录用户
   */
  public void setUser(User user) {
    redisUtil
        .set(Constant.DEFAULT_USER + user.getAccount(), JSONObject.toJSONString(user), expiration);
  }

  /**
   * 缓存账号最新的token
   */
  public void setToken(String account, String token) {
    redisUtil.set(Constant.LOGIN_NEW_TOKEN + account, token, expiration);
  }

  /**
   * 移除token 登出用
   */
  public void removeToken(String account) {
    redisUtil.delete(Constant.LOGIN_NEW_TOKEN + account);
  }

  /**
   * 判断是否是有效的token
   */
  public boolean isValidToken(String account, String token) {

    String cacheToken = getToken(account);

    if (StringUtil.isBlank(cacheToken)) {
      return false;
    }

    if (!cacheToken.equals(token)) {
      return false;
    }

    return true;
  }

  /**
   * 获取token
   * @param account
   * @return
   */
  public String getToken(String account){
    return redisUtil.get(Constant.LOGIN_NEW_TOKEN + account);
  }

  /**
   * 根据前端Token 获取用户
   * @param authHeader
   * @return
   */
  public User getUserByAuthHeader(String authHeader){
    if (StringUtil.isBlank(authHeader) || !authHeader.startsWith(this.tokenHead)) {
      throw new BusinessException("错误token");
    }

    String token = authHeader.substring(this.tokenHead.length());
    return getUserByToken(token);
  }

  /**
   * 根据token获取用户
   * @param token
   * @return
   */
  public User getUserByToken(String token){
    String account = JwtTokenUtil.getUserNameFromToken(token, salt);
    return getUser(account);
  }

  /**
   * 获取当前登录用户
   */
  public User getUser(String account) {

    String userStr = redisUtil.get(Constant.DEFAULT_USER + account);

    if (StringUtil.isBlank(userStr)) {
      throw new BusinessException("无登录用户");
    }

    User user = JSONObject.parseObject(userStr, User.class);
    return user;
  }

  /**
   * token 黑名单
   * 登出缓存 token
   */
  public void setLogoutToken(String token) {
    long time = expiration + Constant.LOGOUT_CACHE_TIME;
    redisUtil.set(Constant.LOGOUT_KEY + token, token, time);
  }

  /**
   * 判断是否已登出
   */
  public boolean isLogout(String token) {
    String tk = redisUtil.get(Constant.LOGOUT_KEY + token);
    if (StringUtil.isNotBlank(tk)) {
      return true;
    }
    return false;
  }

  /**
   * 把当前token 设置为登出---角色 修改权限
   * 添加到token黑名单
   * @param account
   */
  public void setLogout(String account) {
    String token = getToken(account);
    log.info("把当前token 设置为登出---角色 修改权限 account:{} token:{}", account, token);
    if(StringUtil.isNotBlank(token)){
      setLogoutToken(token);
      log.info("把当前token 设置为登出---角色 修改权 成功");
    }
  }
}

